package pl.matt.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.validation.constraints.Min;

import pl.matt.opencv.model.Region;

@Embeddable
public class Rectangle implements Serializable {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	@SuppressWarnings("unused")
	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(Rectangle.class);

	
	
	@Min(0)
	@Column(nullable=false)
	private Integer x;
	@Min(0)
	@Column(nullable=false)
	private Integer y;
	@Min(0)
	@Column(nullable=false)
	private Integer width;
	@Min(0)
	@Column(nullable=false)
	private Integer height;

	public Rectangle(int x, int y, int width, int height) {
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
	}
	
	public Rectangle(Rectangle rectangle) {
		this.x = rectangle.x;
		this.y = rectangle.y;
		this.width = rectangle.width;
		this.height = rectangle.height;
	}	

	public Rectangle(Region region) {
		this.width = region.getWidth();
		this.height = region.getHeight();
		setMiddleX(region.getX());
		setMiddleY(region.getY());
	}

	
	
	public Rectangle() {
	}

	/**
	 * Nie mam pomysłu na lepszą nazwę metody
	 * 
	 * @param second
	 * @return trzeci w kolejności prostokąd
	 * @deprecated
	 */
	public Rectangle getNext(Rectangle second) {
		Rectangle result = new Rectangle(this);
		if (second != null) {
			if (second.height != result.height || second.width != result.width) {
				//throw new IllegalArgumentException("second.height != result.height || second.width != result.width");
				result.height = (result.height + second.height) / 2;
				result.width = (result.width + second.width) / 2;
			}
			result.x = null;
			result.y = null;
			result.setMiddleX(second.getMiddleX() - getMiddleX() + second.getMiddleX());			
			result.setMiddleY(second.getMiddleY() - getMiddleY() + second.getMiddleY());
			if (result.getX() < 0) {
				result.setX(0);
			}
			if (result.getY() < 0) {
				result.setY(0);
			}
		}
		return result;
	}
	
	public int getDistance(Rectangle rectangle) {
		if (rectangle == null) {
			throw new IllegalArgumentException("rectangle == null");
		}
		int middleDiffX = Math.abs(getMiddleX() - rectangle.getMiddleX());
		int middleDiffY = Math.abs(getMiddleY() - rectangle.getMiddleY());
		int diffWidth = Math.abs(getWidth() - rectangle.getWidth());
		int diffHeight = Math.abs(getHeight() - rectangle.getHeight());
		
		return 2 * middleDiffX + 2 * middleDiffY + diffWidth + diffHeight;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((height == null) ? 0 : height.hashCode());
		result = prime * result + ((width == null) ? 0 : width.hashCode());
		result = prime * result + ((getX() == null) ? 0 : getX().hashCode());
		result = prime * result + ((getY() == null) ? 0 : getY().hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Rectangle other = (Rectangle) obj;
		if (height == null) {
			if (other.height != null)
				return false;
		} else if (!height.equals(other.height))
			return false;
		if (width == null) {
			if (other.width != null)
				return false;
		} else if (!width.equals(other.width))
			return false;
		if (getX() == null) {
			if (other.getX() != null)
				return false;
		} else if (!getX().equals(other.getX()))
			return false;
		if (getY() == null) {
			if (other.getY() != null)
				return false;
		} else if (!getY().equals(other.getY()))
			return false;
		return true;
	}

	public Integer getX() {
		return x;
	}

	public void setX(Integer x) {
		this.x = x;
	}

	public Integer getY() {
		return y;
	}

	public void setY(Integer y) {
		this.y = y;
	}

	public Integer getWidth() {
		return width;
	}

	public void setWidth(Integer width) {
		this.width = width;
	}

	public Integer getHeight() {
		return height;
	}

	public void setHeight(Integer height) {
		this.height = height;
	}

	public Integer getMiddleX() {
		return x + width / 2;
	}

	private void setMiddleX(Integer middleX) {
		x = middleX - width / 2;
	}

	public Integer getMiddleY() {
		return y + height / 2;
	}

	private void setMiddleY(Integer middleY) {
		y = middleY - height / 2;
	}

	@Override
	public String toString() {
		return "x: " + getX() + " y: " + getY() + " width: " + getWidth() + " hight: " + getHeight();
	}
	
}
